package com.yesep.netty;

import com.yesep.business.BusinessHandlerThread;
import com.yesep.constant.Constants;
import com.yesep.model.ChannelModel;
import com.yesep.model.MessageBaseModel;
import com.yesep.utils.*;
import io.netty.channel.*;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import static com.yesep.handler.MessageHandler.getStringForExpression;
import static com.yesep.handler.MessageHandler.getValueSplitString;


/**
 * @program: gateway
 * @description: 服务处理器
 * @author: quliang
 * @create: 2019-07-04 11:55
 **/
@ChannelHandler.Sharable
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    private static final Logger log = LoggerFactory.getLogger(NettyServerHandler.class);


    private int loss_connect_time = 0;

    //保证通讯次数+1原子性
    private AtomicInteger connect_count = new AtomicInteger();

    //ip  包号  报文内容/总包数
    private static final Map<String, Map<String, String>> eacheMessageMap = new ConcurrentHashMap<>();

    /**
     * 监听通道获取数据的方法
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (null == ctx) return;

        System.out.println("channelRead收到数据:" + msg.toString());
        try {
            MessageBaseModel message = new MessageBaseModel();
            message.setChannel(ctx.channel());
            message.setMessage((String) msg);
            BusinessHandlerThread.putData(message);
        } catch (Exception ex) {
            ex.printStackTrace();
            log.error("解析异常", ex.getMessage());
        }
    }

    /**
     * 监听心跳方法
     *
     * @param ctx 上下文
     * @param evt 事件类型
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;

            // IdleState.READER_IDLE 状态表示读者闲置,意味就是没收到数据
            if (event.state() == IdleState.READER_IDLE) {
                loss_connect_time++;
                System.out.println("5 秒没有接收到客户端的信息了");
                if (loss_connect_time > 3) {
                    System.out.println("关闭这个不活跃的channel");
                    //删除超时管道缓存
                    NettyChannelManager.getInstance().removeChannel(ctx.channel());
                    //删除超时报文缓存
                    CacheUtils.cacheMessageMap.remove(ctx.channel().remoteAddress().toString());
                    ctx.channel().close();
                }
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }

    /**
     * 通道被激活的方法
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress() + "连接进来了");
        String add = ctx.channel().remoteAddress().toString();
//        String channelId = ctx.channel().id().asLongText();

        System.out.println(ctx.channel().id().asLongText());
        NettyChannelManager.getInstance().putChannel(ctx.channel());

        NettyChannelManager.getInstance().bindMnAndChannel(add, ctx.channel().id().asLongText());

        ChannelModel channelModel = new ChannelModel();
        channelModel.setChannel(ctx.channel());
        channelModel.setCount(connect_count.incrementAndGet());
        channelModel.setTime(new SimpleDateFormat("yyyy MM dd HH:mm:ss").format(new Date(System.currentTimeMillis())));
        channelModel.setIp(ctx.channel().remoteAddress().toString());

        CacheUtils.putInfo(add, channelModel);

        try {
            super.channelActive(ctx);
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
        }
    }

    /**
     * 当链路断开的时候
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        //删除管道缓存
        NettyChannelManager.getInstance().removeChannel(ctx.channel());
        //删除报文缓存
        CacheUtils.cacheMessageMap.remove(ctx.channel().remoteAddress().toString());

        super.channelInactive(ctx);
    }

    /**
     * 异常情况
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        System.out.println("异常断开");
        NettyChannelManager.getInstance().removeChannel(ctx.channel());

        cause.printStackTrace();
        ctx.close();
    }

    /**
     * map<ip,Map<String,报文内容>>
     *
     * @param args
     */
    public static void main(String[] args) {
        String message = "##0466QN=20190723161030000;Flag=7;ST=21;CN=2011;PW=123456;MN=09252062500001;CP=&&DataTime=20190723161030;w01001-Rtd=0.000,w01001-Flag=N;w01003-Rtd=0.000,w01003-Flag=N;w01009-Rtd=0.000,w01009-Flag=N;w01010-Rtd=0.000,w01010-Flag=N;w01014-Rtd=0.000,w01014-Flag=N;";
        String msg = getValueSplitString(getStringForExpression(message, Constants.FLAG_EXPRESSION), Constants.MESSAGE_KEY_VALUE_SPLIT);
//        System.out.println(MessageHandler.bytesToHexString(msg.getBytes()));
        String toBinary = StringUtils.toBinary(Integer.valueOf(msg), 8);
        System.out.println(toBinary);
        System.out.println(toBinary.substring(0, 6));
        System.out.println(toBinary.substring(6, toBinary.length() - 1));
        System.out.println(toBinary.substring(toBinary.length() - 1, toBinary.length()));
        // Map<String, Map<>>
        //ip  包序 报文内容
//        Map<String, Map<String, String>> messageCache = new ConcurrentHashMap<>();
//
//        //包序 报文内容
//        Map<String, String> message = new HashMap<>(10);
//
//        messageCache.put("aa", message);
    }


}
